const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
const resolvePromise = (newPromise, result, resolve, reject) => {
    if(newPromise===result){
      reject(new TypeError('can not return oneself 不能返回自己'))
    }
    if((typeof result==='object'&& result!==null)||typeof result ==='function'){
        const then = result.then
        if(typeof then ==='function'){
            then(res=>{
                resolvePromise(newPromise,res,resolve,reject)
            },err=>{
                reject(err)
            })
        }else{
            resolve(result)
        }
    }else{
        resolve(result)
    }
};
class Jpromise {
    constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.resolveCallback = [];
        this.rejectCallback = [];
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.value = value;
                this.status = RESOLVED;
                this.resolveCallback.map((fn) => fn());
            }
        };
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.reason = reason;
                this.status = REJECTED;
                this.rejectCallback.map((fn) => fn());
            }
        };
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
    }
    then(onResolve, onReject) {
        const newPromise = new Jpromise((resolve, reject) => {
            if (this.status === RESOLVED) {
                setTimeout(() => {
                    try {
                        const result = onResolve(this.value);
                        resolvePromise(newPromise, result, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        const err = onReject(this.reason);
                        resolvePromise(newPromise, err, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }
            if (this.status === PENDING) {
                this.resolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            const result = onResolve(this.value);
                            resolvePromise(newPromise, result, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
                this.rejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            const err = onReject(this.reason);
                            resolvePromise(newPromise, err, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    });
                });
            }
        });
        return newPromise;
    }
}

module.exports = Jpromise;
